#include "mod-icmp6.hpp"


Record * Icmp6Decoder::decode (Packet & pkt, Record & prev)
{
  Icmp6Record &r = this->rec;
  Icmp6Hdr * hdr = (Icmp6Hdr*) pkt.getCur ();
  const int hdrLen = sizeof (Icmp6Hdr);
  
  debug (DEBUG, "Etner ICMP6 decoder");
  if (NULL == hdr || ! pkt.moveCur (hdrLen) || ! r.lock ())
    return NULL;

  r.setData (DEC_ICMP6, hdr, hdrLen);
  debug (DEBUG, "type = %d, code = %d", hdr->icmpType, hdr->icmpCode);
  debug (DEBUG, "Leave ICMP6 decoder");
  return &(this->rec);
}


NDecFilter * Icmp6Decoder::makeFilter (string &name)
{

  Icmp6Filter * f = NULL;

  if (name == "icmp.type")
    f = new Icmp6Filter (Icmp6Filter::FT_ICMP_TYPE);
  else if (name == "icmp.code")
    f = new Icmp6Filter (Icmp6Filter::FT_ICMP_CODE);

  return f;
}


//==========================================================


bool Icmp6Filter::setup (string &arg)
{
  char * e = NULL;
  unsigned int n;
  n = strtoul (arg.c_str (), &e, 0);
  if (*e != '\0' || n > 0xffff)
    {
      this->setErrMsg ("icmp6.(type|code): expected digit \"" +  arg + "\"");
      return false;
    }

  this->data = static_cast <u_int8_t> (n);	 
  return true;
}

void Icmp6Filter::check (NDecResult &res)
{
  u_int8_t tgt;
  Icmp6Record * rp;
  Icmp6Hdr * hdr; 

  if (NULL == (rp = dynamic_cast<Icmp6Record*> (res.getRecord (DEC_ICMP6))) ||
      NULL == (hdr = static_cast<Icmp6Hdr*> (rp->getPtr ())))
    return ;

  switch (this->type)
    {
    case FT_ICMP_TYPE: tgt = hdr->icmpType; break;
    case FT_ICMP_CODE: tgt = hdr->icmpCode; break;
    default:
      assert (0);
    }

  if (tgt == this->data)
    {
      this->pushResult (&tgt, sizeof (tgt));
    }

  return ;
}


